package org.yuning.cloud.starter.configuration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import org.yuning.cloud.common.web.JsonResult;
import org.yuning.cloud.starter.annotation.ResponseWrapperIgnore;
import org.yuning.cloud.starter.utils.JsonUtils;
import org.yuning.cloud.starter.utils.ServletRequestUtils;

/**
 * @author zhangzz
 * @email 291110369@qq.com
 * @date 2023/11/10 8:41
 * @description
 **/
@RestControllerAdvice
@ConditionalOnProperty(prefix = "yuning.cloud", name = "response-wrapper", matchIfMissing = true)
public class ResponseDataWrapper implements ResponseBodyAdvice {

    public static String FEIGN_REQUEST_HEADER_NAME = "yn-feign-request";
    public static String FEIGN_REQUEST_HEADER_VALUE = "yn-feign-request";

    private Logger log = LoggerFactory.getLogger(ResponseDataWrapper.class);

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        // 来自非 Feign 请求和未使用 @ResponseWrapperIgnore 注解的返回数据，统一进行数据包装
        return !isFeignRequest() || !returnType.hasMethodAnnotation(ResponseWrapperIgnore.class)
                || returnType.getParameterType().isAssignableFrom(Void.class);
    }

    private boolean isFeignRequest() {
        String header = ServletRequestUtils.currentRequest().getHeader(FEIGN_REQUEST_HEADER_NAME);
        return FEIGN_REQUEST_HEADER_VALUE.equals(header);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        log.debug("ResponseDataWrapper body {}, selectedConverterType {}, selectedContentType",
                body, selectedConverterType, selectedContentType);
        // StringHttpMessageConverter 特殊处理
        if (StringHttpMessageConverter.class.isAssignableFrom(selectedConverterType)) {
            HttpHeaders headers = response.getHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            return JsonUtils.object2JsonString(JsonResult.success(body));
        }
        if (body == null) {
            return JsonResult.success(null, "请求成功");
        } else if (body instanceof JsonResult) {
            return body;
        } else {
            return JsonResult.success(body);
        }
    }
}
